﻿///////////////////////////////////////////////////////////////////////////////
//
//  RootControl.xaml.cs
//
// 
// © 2008 Microsoft Corporation. All Rights Reserved.
//
// This file is licensed as part of the Silverlight 1.1 SDK, for details look here: http://go.microsoft.com/fwlink/?LinkID=111970&clcid=0x409
//
///////////////////////////////////////////////////////////////////////////////
namespace SilverlightChess 
{
	using System;
	using System.IO;
	using System.Windows;
	using System.Windows.Browser;
	using System.Windows.Controls;
	using System.Windows.Threading;
	using GarboChess;
	using System.Windows.Controls.Primitives;
    using System.Collections.Generic;


	[ScriptableType]
	public class JScriptPlayer
	{
		private string fen;
		private ushort move;
		private int nodes;
		private int time;
        private List<ushort> moves;

		[ScriptableMember]
		public string Fen
		{
			get { return this.fen; }
			set
			{
				this.fen = value;
                HtmlPage.Window.Invoke("ResetGame");
				HtmlPage.Window.Invoke("InitializeFromFen", value);
			}
		}

        public List<ushort> ValidMoves()
        {
            HtmlPage.Window.Invoke("GenerateValidMoves");
            return this.moves;
        }

		public ushort MakeMove()
		{
			HtmlPage.Window.Invoke("Search");
			return this.move;
		}

		public int Nodes
		{
			get { return this.nodes; }
		}

		public int Time
		{
			get { return this.time; }
		}

		[ScriptableMember()]
		public void MoveComplete(ushort move, int nodes, int time)
		{
			this.move = move;
			this.nodes = nodes;
			this.time = time;
		}
	}

	public partial class RootControl : UserControl 
	{
		private Position position = new Position();
		private Searcher searcher;
		private JScriptPlayer jscriptPlayer;
		private DispatcherTimer timer = new DispatcherTimer();
		private bool isGameOver = false;

		public RootControl() 
		{
			this.InitializeComponent();

			this.position.ResetBoard();

			this.jscriptPlayer = new JScriptPlayer();
			HtmlPage.RegisterScriptableObject("Player", this.jscriptPlayer);

			this.searcher = new Searcher(this.position);
			this.searcher.AllottedTime = 200;

			this.chessBoard.UserMove += this.OnUserMove;
			this.chessBoard.AnimationCompleted += this.OnChessBoardAnimationCompleted;

			this.whiteSelector.SelectedPlayer = 0;
			this.blackSelector.SelectedPlayer = 1;
			this.whiteSelector.SelectionChanged += this.OnSelectorSelectionChanged;
			this.blackSelector.SelectionChanged += this.OnSelectorSelectionChanged;
			
			this.timer.Interval = TimeSpan.FromMilliseconds(10);
			this.timer.Tick += this.OnTimerTick;

			this.LayoutUpdated += this.OnRootControlLayoutUpdated;

			this.Loaded += this.OnRootControlLoaded;
		}

		private void OnRootControlLoaded(object sender, RoutedEventArgs e)
		{
			this.chessBoard.Position = this.position;
		}

		private void OnRootControlLayoutUpdated(object sender, EventArgs e)
		{
			this.whiteSelector.Width = this.chessBoard.ActualWidth;
			this.blackSelector.Width = this.chessBoard.ActualWidth;
		}

		private void OnUserMove(ushort move)
		{
			this.position.MakeMove(move);
			this.chessBoard.UpdateForNewPosition();
		}

		private void OnChessBoardAnimationCompleted()
		{
           // ushort moves = HtmlPage.Window.Invoke("GenerateValidMoves");
            
                       
			if (this.position.GenerateValidMoves().Count == 0)
           // if (this.jscriptPlayer.ValidMoves().Count == 0)
			{
				if (this.isGameOver)
				{
					return;
				}

				this.isGameOver = true;
				// Game over state
				WinnerDisplayControl winner = new WinnerDisplayControl();
               	winner.Victor = this.position.ToMove == 0 ? "White" : "Black";
				winner.Completed += this.OnWinnerCompleted;
				winner.Width = 400;
				winner.Height = 250;
                this.LayoutRoot.Children.Add(winner);
                
			}
			else
			{
				this.DoAITurn();
			}
		}

		private void OnWinnerCompleted(object sender, RoutedEventArgs e)
		{
			this.isGameOver = false;
			this.LayoutRoot.Children.Remove((UIElement)sender);
			
			this.position.ResetBoard();
			this.chessBoard.UpdateForNewPosition();
		}

		private void OnSelectorSelectionChanged(object sender, EventArgs e)
		{
			this.DoAITurn();
		}

		private void OnTimerTick(object sender, EventArgs e)
		{
			this.timer.Stop();
			this.chessBoard.UpdateForNewPosition();
		}

		private void DoAITurn()
		{
			int color = this.position.ToMove;
			PlayerSelector selector = color == 0 ? this.blackSelector : this.whiteSelector;

			if (selector.SelectedPlayer == 0)
			{
				this.UpdateNodesSec(color, "Human", 3, 1000);
				return;
			}

			if (selector.SelectedPlayer == 1)
			{
				this.position.MakeMove(this.searcher.Search());
				this.UpdateNodesSec(color, "C#", this.searcher.QNodeCount + this.searcher.NodeCount, this.searcher.AllottedTime);
			}
			else if (selector.SelectedPlayer == 2)
			{
				this.jscriptPlayer.Fen = this.position.GetFen();
				this.position.MakeMove(this.jscriptPlayer.MakeMove());
                this.UpdateNodesSec(color, "JS", this.jscriptPlayer.Nodes,this.jscriptPlayer.Time);
                
			}

			this.timer.Start();
		}

		private void UpdateNodesSec(int color, string aiName, int nodes, int time)
		{
			long nodesSec = ((long)nodes * 1000) / time;
			if (color == 0)
			{
				this.blackNodesSec.Text = nodesSec.ToString();
				this.blackNodesTitle.Text = aiName + " Nodes/Sec.";
			}
			else
			{
				this.whiteNodesSec.Text = nodesSec.ToString();
				this.whiteNodesTitle.Text = aiName + " Nodes/Sec.";
			}
		}
	}
}